﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace TravianLib
{
    public class building : ICloneable
    {        
        public enum buildingType {
  	Woodcutter = 1,
    MainBuilding  = 15,
    GreatBarracks = 29,
 	ClayPit =2,
    RallyPoint 	= 16,	        
    GreatStable = 30,
 	IronMine =	3	, 	Marketplace 	 = 17,	         	CityWall = 31,
 	Cropland =	4	, 	Embassy 	 = 18,	        	EarthWall = 32,
 	Sawmill =	5	, 	Barracks 	 = 19,	         	Palisade = 33,
 	Brickyard 	=6	, 	Stable 		  = 20,       	Stonemason = 34,
 	IronFoundry =7		, 	Workshop  = 21,		        	Brewery = 35,
 	GrainMill =	8	, 	Academy  = 22,		    	Trapper = 36,
 	Bakery =	9	, 	Cranny 		   = 23,       	HerosMansion  = 37,
 	Warehouse =10		, 	TownHall 	 = 24,    	 	GreatWarehouse  = 38,
 	Granary 	=11	, 	Residence 	 = 25,	         	GreatGranary = 39,
 	Blacksmith =	12	, 	Palace 	 = 26,	        	WonderoftheWorld = 40,
 	Armoury 	=13	, 	Treasury 	    = 27,     Unknown = 99, Free = 100,
 	TournamentSquare =14   , 	TradeOffice  = 28, RallyPointSite=101,CityWallSite=102
        }

        private int id_;
        private ushort level_;
        private HTTPFetch httpFetch_;
        private buildingType gid_;
        private bdReqs bdReqs_ = Utils.TravianData;

        public buildingType GID { get { return gid_; } set { gid_ = value; } }
        public ushort Level { get { return level_; } set { level_ = value; } }
        public int ID { get { return id_; } }
        public resources UpgradeCosts
        {
            get
            {
                resources output = new resources();

                bdReqs.costsRow q = (from c in bdReqs_.costs
                                     where (building.buildingType)c.GID == GID && c.Level == Level + 1
                                     select c).SingleOrDefault();
                if (q != null)
                {
                    output.wood = q.Wood;
                    output.clay = q.Clay;
                    output.iron = q.Iron;
                    output.crop = q.Crop;
                }
                return output;
            }
        }
        public TimeSpan BuildTime(int MBLevel)
        {
            TimeSpan result = new TimeSpan();

            var q = (from c in bdReqs_.buildingTimes
                     where (building.buildingType)c.GID == GID && c.Level == Level + 1 && c.MBLevel == MBLevel
                     select c.Time).Take(1);

            if (q != null)
            {
                result = q.SingleOrDefault();
            }
            return result;
        }
        public bool enoughFoodToUpgrade(resources production)
        {
            if (production.crop - 2 >= (from c in bdReqs_.costs
                                        where (building.buildingType)c.GID == GID && c.Level == Level + 1
                                        select c.Consumption).SingleOrDefault())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool canUpgrade(resources current)
        {
            resources tmp = UpgradeCosts;
            if (tmp.wood > current.wood ||
                tmp.clay > current.clay ||
                tmp.iron > current.iron ||
                tmp.crop > current.crop
                )
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        public string upgrade(resources current, int id)
        {
            if (canUpgrade(current))
            {
                string output = httpFetch_.createHTTPrequest("/build.php?id=" + id);
                Regex rgx = new Regex("(dorf[0-9].php.a.*?)\"");
                if (rgx.Matches(output).Count == 1)
                {

                    output = httpFetch_.createHTTPrequest("/" + rgx.Matches(output)[0].Groups[1].Value);
                }
                else if (rgx.Matches(output).Count > 1)
                {
                    foreach (Match match in rgx.Matches(output))
                    {
                        if (match.Value.Contains("a=" + ((int)this.gid_)))
                        {
                            output = httpFetch_.createHTTPrequest("/" + match.Groups[1].Value);
                            break;
                        }
                    }
                }
                return output;
            }
            else
            {
                return "";
            }
        }
  
        public void buildingDone(int id, buildingType GID) {
            this.level_++;
            id_ = id;
            gid_ = GID;
        }
        public building(int id, buildingType title, ushort level, HTTPFetch hf)
        {
            id_ = id;
            level_ = level;
            gid_ = title;
            httpFetch_ = hf;          
        }
        public object Clone()
        {
            return this.MemberwiseClone();
        }
        public double resourceWaitTime(resources current, resources production)
        {
            try
            {
                double output = 0;
                resources reqs = UpgradeCosts;
                if (reqs.wood > current.wood)
                {
                    output = (double)(reqs.wood - current.wood) / (double)production.wood;
                }
                if (reqs.clay > current.clay)
                {
                    if ((double)(reqs.clay - current.clay) / production.clay > output)
                    {
                        output = (double)(reqs.clay - current.clay) / (double)production.clay;
                    }
                }
                if (reqs.iron > current.iron)
                {
                    if ((double)(reqs.iron - current.iron) / production.iron > output)
                    {
                        output = (double)(reqs.iron - current.iron) / (double)production.iron;
                    }
                }
                if (reqs.crop > current.crop)
                {
                    if ((double)(reqs.crop - current.crop) / production.crop > output)
                    {
                        output = (double)(reqs.crop - current.crop) / (double)production.crop;
                    }
                }
                return output;
            }
            catch
            {
                return -1;
            }
        }
    }
}
